package com.seanLab.tool.TagSuggestModel;

import com.seanLab.domain.TagInfo;
import static com.seanLab.tool.TagSuggestModel.RawInfoType.*;

import java.util.*;
import java.util.Map.Entry;


/***
 * Return tags extracted from different sources, and mixed them by weight
 */
public class ModelKernelStrategyMixed implements ModelKernelStrategy {
    private static HashMap<RawInfoType, Double> DefaultWeightMap = getDefaultWeight();
    private HashMap<RawInfoType, Double> weightMap = new HashMap<>();

    private static HashMap<RawInfoType, Double> getDefaultWeight() {
        HashMap<RawInfoType, Double> weightMap = new HashMap<>();
        weightMap.put(TAG, 0.0);
        weightMap.put(TITLE, 1.0);
        weightMap.put(CONTENT, 1.0);
        weightMap.put(PARA_ABOVE_IMAGE, 2.0);
        weightMap.put(PARA_UNDER_IMAGE, 2.0);
        weightMap.put(DESC_OF_IMAGE, 2.0);
        weightMap.put(SEMANTIC_OF_IMAGE, 0.0);
        return weightMap;
    }

    public ModelKernelStrategyMixed() {
        weightMap = DefaultWeightMap;
    }

    @Override
    public List<TagInfo> doSuggest(List<List<TagInfo>> tagsList, RawInfoType[] rawInfoTypes) {
        HashMap<String, Tuple> tagMap = new HashMap<>();
        for (List<TagInfo> tags : tagsList) {
            RawInfoType type = rawInfoTypes[tagsList.indexOf(tags)];
            for (TagInfo tag : tags) {
                String tagName = tag.getTagName();
                Double tagScore = tag.getTagScore() * weightMap.get(type);
                if (tagMap.containsKey(tagName)) {
                    Tuple value = tagMap.get(tagName);
                    if (tagScore > value.max) {
                        value.max = tagScore;
                        value.source = tag.getTagSource();
                    }
                    value.score = value.score + tagScore;
                }
                else {
                    tagMap.put(tagName, new Tuple(tagScore, tagScore, tag.getTagSource()));
                }
            }
        }
        List<TagInfo> finalTags = new ArrayList<>();
        for (Entry<String, Tuple> entry : tagMap.entrySet()) {
            TagInfo tag = new TagInfo(null, entry.getKey(), entry.getValue().source, entry.getValue().score, 0);
            finalTags.add(tag);
        }
        Collections.sort(finalTags, new Comparator<TagInfo>() {
            @Override
            public int compare(TagInfo o1, TagInfo o2) {
                return Double.compare(o2.getTagScore(), o1.getTagScore());
            }
        });
        return finalTags;
    }

    private class Tuple {

        public Double score;

        public Double max;

        public String source;

        public Tuple(Double a, Double b, String c) {
            score = a;
            max = b;
            source = c;
        }
    }
}
